package com.tju.ocean_ecology_website.service.impl;

import com.tju.ocean_ecology_website.config.FileUploadConfig;
import com.tju.ocean_ecology_website.dao.FileUploadDao;
import com.tju.ocean_ecology_website.entity.Activity;
import com.tju.ocean_ecology_website.entity.FileUpload;
import com.tju.ocean_ecology_website.entity.News;
import com.tju.ocean_ecology_website.entity.OrganizationInfo;
import com.tju.ocean_ecology_website.entity.User;
import com.tju.ocean_ecology_website.entity.EducationResource;
import com.tju.ocean_ecology_website.mapper.UserMapper;
import com.tju.ocean_ecology_website.service.ActivityService;
import com.tju.ocean_ecology_website.service.FileUploadService;
import com.tju.ocean_ecology_website.service.NewsService;
import com.tju.ocean_ecology_website.service.OrganizationInfoService;
import com.tju.ocean_ecology_website.service.EducationResourceService;
import com.tju.ocean_ecology_website.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 文件上传记录表(FileUpload)表服务实现类
 *
 * @author shaolong
 * @since 2025-05-10 10:00:00
 */
@Service("fileUploadService")
public class FileUploadServiceImpl implements FileUploadService {
    private static final Logger logger = LoggerFactory.getLogger(FileUploadServiceImpl.class);

    @Resource
    private FileUploadDao fileUploadDao;

    @Autowired
    private FileUploadConfig fileUploadConfig;

    @Autowired(required = false)
    private UserService userService;

    @Autowired(required = false)
    private UserMapper userMapper;

    @Autowired(required = false)
    private ActivityService activityService;

    @Autowired(required = false)
    private NewsService newsService;

    @Autowired(required = false)
    private OrganizationInfoService organizationInfoService;

    @Autowired(required = false)
    private EducationResourceService educationResourceService;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public FileUpload queryById(Long id) {
        return this.fileUploadDao.queryById(id);
    }

    /**
     * 分页查询
     *
     * @param fileUpload 筛选条件
     * @param pageRequest 分页对象
     * @return 查询结果
     */
    @Override
    public Page<FileUpload> queryByPage(FileUpload fileUpload, PageRequest pageRequest) {
        long total = this.fileUploadDao.count(fileUpload);
        return new PageImpl<>(this.fileUploadDao.queryAllByLimit(fileUpload, pageRequest), pageRequest, total);
    }

    /**
     * 新增数据
     *
     * @param fileUpload 实例对象
     * @return 实例对象
     */
    @Override
    public FileUpload insert(FileUpload fileUpload) {
        this.fileUploadDao.insert(fileUpload);
        return fileUpload;
    }

    /**
     * 修改数据
     *
     * @param fileUpload 实例对象
     * @return 实例对象
     */
    @Override
    public FileUpload update(FileUpload fileUpload) {
        this.fileUploadDao.update(fileUpload);
        return this.queryById(fileUpload.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Long id) {
        // 查询文件信息
        FileUpload fileUpload = this.queryById(id);
        if (fileUpload == null) {
            return false;
        }

        // 删除物理文件
        try {
            Path filePath = Paths.get(fileUpload.getFilePath());
            if (Files.exists(filePath)) {
                Files.delete(filePath);
            }
        } catch (IOException e) {
            // 删除物理文件失败，但仍然删除数据库记录
            e.printStackTrace();
        }

        // 删除数据库记录
        return this.fileUploadDao.deleteById(id) > 0;
    }

    /**
     * 上传文件
     *
     * @param file 文件对象
     * @param type 文件类型
     * @param userId 用户ID
     * @return 文件上传记录
     * @throws IOException IO异常
     */
    @Override
    public FileUpload uploadFile(MultipartFile file, String type, Long userId) throws IOException {
        // 验证文件是否为空
        if (file.isEmpty()) {
            throw new IllegalArgumentException("文件为空");
        }

        // 验证文件类型
        String contentType = file.getContentType();
        if (contentType == null || !fileUploadConfig.getAllowedImageTypes().contains(contentType)) {
            throw new IllegalArgumentException("不支持的文件类型，仅支持JPG/PNG/GIF/WEBP/BMP格式的图片");
        }

        // 验证文件大小
        if (file.getSize() > fileUploadConfig.getMaxFileSize()) {
            throw new IllegalArgumentException("文件大小超过限制，最大支持" + (fileUploadConfig.getMaxFileSize() / 1024 / 1024) + "MB");
        }

        // 生成文件名
        String originalFilename = file.getOriginalFilename();
        String extension = originalFilename != null ? originalFilename.substring(originalFilename.lastIndexOf(".")) : ".jpg";
        String fileName = UUID.randomUUID().toString() + extension;

        // 按照上传类型和日期组织文件目录结构
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
        String datePath = dateFormat.format(new Date());
        String uploadDir = fileUploadConfig.getUploadRootDir() + "/" + type + "/" + datePath;
        Path uploadPath = Paths.get(uploadDir);

        // 创建目录
        if (!Files.exists(uploadPath)) {
            Files.createDirectories(uploadPath);
        }

        // 保存文件
        Path filePath = uploadPath.resolve(fileName);
        Files.copy(file.getInputStream(), filePath);

        // 生成访问URL
        String fileUrl;
        if (fileUploadConfig.getBaseUrl() != null && !fileUploadConfig.getBaseUrl().isEmpty()) {
            // 如果配置了基础URL，使用绝对URL
            fileUrl = fileUploadConfig.getBaseUrl();
            if (!fileUrl.endsWith("/")) {
                fileUrl += "/";
            }
            fileUrl += fileUploadConfig.getUploadRootDir() + "/" + type + "/" + datePath + "/" + fileName;
        } else {
            // 否则使用相对URL
            fileUrl = "/" + fileUploadConfig.getUploadRootDir() + "/" + type + "/" + datePath + "/" + fileName;
        }

        // 创建文件上传记录
        FileUpload fileUpload = new FileUpload();
        fileUpload.setOriginalName(originalFilename);
        fileUpload.setFileName(fileName);
        fileUpload.setFilePath(uploadDir + "/" + fileName);
        fileUpload.setFileUrl(fileUrl);
        fileUpload.setFileSize(file.getSize());
        fileUpload.setFileType(contentType);
        fileUpload.setUploadType(type);
        fileUpload.setUserId(userId);
        fileUpload.setCreateTime(new Date());

        // 保存记录到数据库
        this.fileUploadDao.insert(fileUpload);

        return fileUpload;
    }

    /**
     * 根据上传类型和用户ID查询文件列表
     *
     * @param type 上传类型
     * @param userId 用户ID
     * @param pageRequest 分页对象
     * @return 文件列表
     */
    @Override
    public Page<FileUpload> queryByTypeAndUserId(String type, Long userId, PageRequest pageRequest) {
        long total = this.fileUploadDao.countByTypeAndUserId(type, userId);
        List<FileUpload> fileUploads = this.fileUploadDao.queryByTypeAndUserId(type, userId, pageRequest);
        return new PageImpl<>(fileUploads, pageRequest, total);
    }

    /**
     * 更新业务表中的图片URL
     *
     * @param type 上传类型
     * @param fileUrl 文件URL
     * @param targetId 目标记录ID
     * @param userId 用户ID
     * @return 是否成功
     */
    @Override
    @Transactional
    public boolean updateBusinessImageUrl(String type, String fileUrl, Long targetId, Long userId) {
        try {
            // 根据上传类型更新不同的业务表
            switch (type) {
                case "avatar":
                    // 更新用户头像
                    if (userService != null) {
                        User user = userService.queryById(targetId);
                        if (user != null) {
                            user.setAvatar(fileUrl);
                            user.setUpdateTime(new Date());
                            userService.update(user);
                            return true;
                        }
                    } else if (userMapper != null) {
                        User user = userMapper.findById(targetId);
                        if (user != null) {
                            user.setAvatar(fileUrl);
                            user.setUpdateTime(new Date());
                            userMapper.update(user);
                            return true;
                        }
                    }
                    break;

                case "activity":
                case "project":
                    // 更新活动/项目图片
                    if (activityService != null) {
                        Activity activity = activityService.queryById(targetId);
                        if (activity != null) {
                            activity.setImage(fileUrl);
                            activity.setUpdateTime(new Date());
                            activityService.update(activity);
                            return true;
                        }
                    }
                    break;

                case "banner":
                    // 更新轮播图图片
                    // 这里需要根据实际的banner表结构来实现
                    logger.info("更新Banner图片URL: {}", fileUrl);
                    return true;

                case "logo":
                    // 更新组织Logo
                    if (organizationInfoService != null) {
                        OrganizationInfo org = organizationInfoService.queryById(targetId);
                        if (org != null) {
                            org.setLogo(fileUrl);
                            organizationInfoService.update(org);
                            return true;
                        }
                    }
                    break;

                case "news":
                    // 更新新闻封面图
                    if (newsService != null) {
                        News news = newsService.queryById(targetId);
                        if (news != null) {
                            news.setCoverImage(fileUrl);
                            news.setUpdateTime(new Date());
                            newsService.update(news);
                            return true;
                        }
                    }
                    break;

                case "education":
                    // 更新教育资源封面图
                    if (educationResourceService != null) {
                        EducationResource resource = educationResourceService.queryById(targetId);
                        if (resource != null) {
                            resource.setCoverImage(fileUrl);
                            resource.setUpdateTime(new Date());
                            educationResourceService.update(resource);
                            return true;
                        }
                    }
                    break;

                default:
                    logger.warn("不支持的上传类型: {}", type);
                    return false;
            }

            logger.warn("更新业务表失败，找不到目标记录，类型: {}, 目标ID: {}", type, targetId);
            return false;
        } catch (Exception e) {
            logger.error("更新业务表图片URL失败", e);
            return false;
        }
    }

    /**
     * 上传文件并更新业务表
     *
     * @param file 文件对象
     * @param type 文件类型
     * @param targetId 目标记录ID
     * @param userId 用户ID
     * @return 文件上传记录和更新结果
     * @throws IOException IO异常
     */
    @Override
    @Transactional
    public Map<String, Object> uploadFileAndUpdateBusiness(MultipartFile file, String type, Long targetId, Long userId) throws IOException {
        Map<String, Object> result = new HashMap<>();

        // 1. 上传文件
        FileUpload fileUpload = this.uploadFile(file, type, userId);
        result.put("fileUpload", fileUpload);

        // 2. 更新业务表
        boolean updateResult = false;
        if (targetId != null) {
            updateResult = this.updateBusinessImageUrl(type, fileUpload.getFileUrl(), targetId, userId);
        }
        result.put("updateBusiness", updateResult);

        return result;
    }
}
